﻿
namespace n_MyObject
{
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using n_MyObjectList;
using n_MyPanel;
using n_MyIns;
using n_EventIns;
using n_GVar;
using n_GUIset;
using n_SimModule;
using n_Sprite;
using n_SOblect;

//*****************************************************
//组件类
public abstract class MyObject
{
	public static bool GroupReplace = false;
	string v_Name;
	public string Name {
		get {
			if( GroupReplace ) {
				return n_GroupList.Group.GetFullName( this.GroupMes, v_Name );
			}
			else {
				return v_Name;
			}
		}
		set {
			v_Name = value;
		}
	}
	
	public int Index;
	
	public bool Visible;
	public bool GroupVisible;
	
	//分组信息 (没有分组则为null)
	public string GroupMes;
	
	protected int myX;
	public int SX {
		get {
			return myX;
		}
		set {
			//if( !NotChangeTarget ) {
				targetSX = value;
			//}
			myX = value;
		}
	}
	public int MidX {
		get { return myX + this.Width / 2; }
	}
	protected int myY;
	public int SY {
		get {
			return myY;
		}
		set {
			//if( !NotChangeTarget ) {
				targetSY = value;
			//}
			myY = value;
		}
	}
	public int MidY {
		get { return myY + this.Height / 2; }
	}
	
	public bool AutoMove;
	public int targetSX;
	public int targetSY;
	
	protected int WidthPadding;
	protected int HeightPadding;
	
	public int Width, Height;
	
	public int ChipIndex;
	public int Angle;  // 0, 90, 180, 240
	
	//是否允许悬浮上空
	public bool CanFloat;
	//鼠标是否在组件上(用于画组件边框高亮)
	public bool ignoreHit;
	public int isNewTick;
	public const int MaxNewTick = 3;
	
	//关联的仿真对象
	SObject v_TargetSObject;
	public int TargetSObjectIndex;
	public SObject TargetSObject {
		get {
			return v_TargetSObject;
		}
		set {
			v_TargetSObject = value;
			if( v_TargetSObject != null ) {
				TargetSObjectIndex = v_TargetSObject.Index;
			}
		}
	}
	
	public SObject InitTargetSObject;
	public SObject CreateInitTargetSObject;
	
	//-----------------------------------------------------------------
	
	//是否具有初始化仿真参数
	public bool ExistSimValue;
	
	public float SimMidX;
	public float SimMidY;
	public float SimWidth;
	public float SimHeight;
	public float SimAngle;
	public bool SimVisible;
	
	//马达参数设置
	public bool SimSwapPin;
	public int SimStartPower;
	public int SimSpeedDown;
	public int SimInertia;
	
	//角色参数
	public string SpriteFilePath;
	public float SimRolX;
	public float SimRolY;
	public float SimimgAngle;
	public int ImgIndex;
	public string NotHitList;
	
	//-----------------------------------------------------------------
	
	//所在的组件列表对象
	public MyObjectList myObjectList;
	
	public bool IgnoreHighLight;
	
	public bool isMouseOnBase;
	public bool isMousePress;
	public int Last_mX, Last_mY;
	
	//组件是否被移动过, 如果为真, 则会递归调用一个碰撞处理函数
	public bool isMoved;
	
	//组件是否为高亮选中
	public bool isHighLight;
	
	//组件是否右键选中
	public bool isSelect;
	
	//是否需要移动
	public bool NeedPasteMove;
	public static int PasteMoveTime;
	
	public MyPanel VPanel;
	
	public int ExYHPadding;
	public int ExYLPadding;
	public int ExXPadding;
	
	public int[] DataList;
	public bool DataListChanged;
	
	protected bool OnYPadding;
	
	
	public int[] DebugValue;
	public const int DebugLength = 400;
	public int DebugIndex;
	public bool DebugOpen;
	
	int MinDebugData;
	int MaxDebugData;
	
	static SolidBrush DebugBackBrush;
	static SolidBrush DebugTextBrush;
	static Pen LinePen0;
	static Pen LinePen1;
	
	//==========================================================================
	
	//初始化 - 注意要加上1, 避免和派生类的 Init 冲突
	public static void Init1()
	{
		DebugBackBrush = new SolidBrush( Color.FromArgb( 80, Color.CornflowerBlue ) );
		DebugTextBrush = new SolidBrush( Color.FromArgb( 150, Color.CornflowerBlue ) );
		
		LinePen0 = new Pen( Color.LightBlue, 3 );
		LinePen1 = new Pen( Color.CornflowerBlue, 1 );
		
		LinePen0.StartCap = LineCap.Round;
		LinePen0.EndCap = LineCap.Round;
		LinePen1.StartCap = LineCap.Round;
		LinePen1.EndCap = LineCap.Round;
	}
	
	//构造函数,根据文件名加载组件,文件名为全路径
	public MyObject()
	{
		ExYLPadding = 0;
		ExYHPadding = 0;
		ExXPadding = 0;
		
		//WidthPadding = 0;
		//Heightpadding = 40;
		
		AutoMove = false;
		
		Visible = true;
		GroupVisible = true;
		
		WidthPadding = 10;
		HeightPadding = 0;
		
		PasteMoveTime = 0;
		NeedPasteMove = false;
		CanFloat = false;
		isMousePress = false;
		Last_mX = 0;
		Last_mY = 0;
		SX = 0;
		SY = 0;
		Angle = 0;
		isMoved = false;
		isHighLight = false;
		isSelect = false;
		//LastIsHighLight = false;
		IgnoreHighLight = false;
		ChipIndex = -1;
		isNewTick = 0;
		
		NotHitList = "";
		
		DataList = new int[1024 + 1];
		DataListChanged = false;
		
		DebugOpen = false;
		DebugValue = new int[DebugLength];
		DebugIndex = 0;
		
		MinDebugData = -50;
		MaxDebugData = 50;
		
		TargetSObject = null;
		
		ExistSimValue = false;
		
		SimMidX = 0;
		SimMidY = 0;
		SimAngle = 0;
		SimVisible = true;
		
		SimSwapPin = false;
		SimStartPower = 5;
		SimSpeedDown = 50;
		SimInertia = 50;
	}
	
	//是否可见
	public bool isVisible()
	{
		return Visible && GroupVisible;
	}
	
	//判断鼠标是否在当前组件上
	public bool MouseIsInside备份竖直面板( int mX, int mY )
	{
		//判断是否在组件上
		if( mX >= MidX - Width / 2 && mX <= MidX + Width / 2 && mY >= MidY - Height / 2 - ExYHPadding && mY <= MidY + Height / 2 + ExYLPadding ) {
			return true;
		}
		//判断是否在面板上
		if( this.isHighLight && this.VPanel.Visible && this.VPanel.MouseIsInside( mX, mY ) ) {
			return true;
		}
		//判断是否在组件下方
		if( this.isHighLight && mX > MidX - Width / 2 && mX < MidX + Width / 2 && mY > MidY + Height / 2 && mY < this.VPanel.Y ) {
			return true;
		}
		//判断是否在面板上方
		if( this.isHighLight && mX > this.VPanel.X && mX < this.VPanel.X + this.VPanel.Width && mY > MidY + Height / 2 && mY < this.VPanel.Y ) {
			return true;
		}
		//判断是否在面板上
		if( this.isHighLight && MouseIsInEX( mX, mY ) ) {
			return true;
		}
		return false;
	}
	
	//判断鼠标是否在当前组件上
	public bool MouseIsInside备份右边面板( int mX, int mY )
	{
		//判断是否在组件上
		if( mX >= MidX - Width / 2 && mX <= MidX + Width / 2 && mY >= MidY - Height / 2 - ExYHPadding && mY <= MidY + Height / 2 + ExYLPadding ) {
			return true;
		}
		//判断是否在面板上
		if( this.isHighLight && this.VPanel.Visible && this.VPanel.MouseIsInside( mX, mY ) ) {
			return true;
		}
		//判断是否在组件右方
		if( this.isHighLight && mY > MidY - Height / 2 && mY < MidY + Height / 2 && mX > MidX + Width / 2 && mX < this.VPanel.X ) {
			return true;
		}
		//判断是否在面板左方
		if( this.isHighLight && mY > this.VPanel.Y && mY < this.VPanel.Y + this.VPanel.Height && mX > MidX + Width / 2 && mX < this.VPanel.X ) {
			return true;
		}
		//判断是否在面板上
		if( this.isHighLight && MouseIsInEX( mX, mY ) ) {
			return true;
		}
		return false;
	}
	
	//判断鼠标是否在当前组件上
	public bool MouseIsInside( int mX, int mY )
	{
		isMouseOnBase = false;
		OnYPadding = false;
		
		//判断是否在组件上
		if( mX >= MidX - Width / 2 - ExXPadding && mX <= MidX + Width / 2 + ExXPadding && mY >= MidY - Height / 2 - ExYHPadding && mY <= MidY + Height / 2 + ExYLPadding ) {
			isMouseOnBase = true;
			if( mY < MidY - Height / 2 || mY > MidY + Height / 2 ) {
				OnYPadding = true;
			}
			return true;
		}
		return false;
	}
	
	//刷新面板位置
	public void RefreshPanelLocation()
	{
		if( this.VPanel != null ) {
			//this.VPanel.X = myX + WidthPadding;
			//this.VPanel.Y = myY + Height + Heightpadding;
			
			this.VPanel.X = myX + Width + WidthPadding;
			this.VPanel.Y = myY;
			
			//this.VPanel.X = myX - this.VPanel.Width - WidthPadding;
			//this.VPanel.Y = myY;
		}
	}
	
	//仿真初始化
	public void ResetSimBase()
	{
		DebugOpen = false;
		MinDebugData = -50;
		MaxDebugData = 50;
	}
	
	//组件移除
	public abstract void Remove();
	
	//组件扩展函数
	public abstract bool MouseIsInEX( int mX, int mY );
	
	//组件绘制工作1
	//绘制组件的外形等,基础绘制工作
	public abstract void Draw1( Graphics g );
	
	//组件绘制工作2
	//绘制组件的端口链接导线,需要在所有组件基础绘制完成之后进行
	//绘制端口的方框背景
	public abstract void Draw2( Graphics g );
	
	//组件绘制工作3
	//绘制组件的端口和名称,需要在所有链接导线绘制完成之后进行
	public abstract void Draw3( Graphics g );
	
	//绘制仿真
	public abstract void DrawSim( Graphics g );
	
	//组件绘制工作3
	//绘制组件的端口和名称,需要在所有链接导线绘制完成之后进行
	public abstract void DrawHighLight( Graphics g );
	
	//鼠标按下事件, 在组件中返回 true,不在组件中返回 false.
	public abstract bool MouseDown1( int mX, int mY );
	
	//专用于面板鼠标按下事件, 在面板中返回 true,不在面板中返回 false.
	public bool MouseDown2( int mX, int mY )
	{
		if( !isHighLight ) {
			return false;
		}
		if( this.VPanel == null ) {
			return false;
		}
		return this.VPanel.MouseDown( mX, mY );
	}
	
	//鼠标松开事件
	public abstract void MouseUp1( int mX, int mY );
	
	//鼠标松开事件
	public void MouseUp2( int mX, int mY )
	{
		if( this.VPanel != null ) {
			this.VPanel.MouseUp( mX, mY );
		}
		
		//判断是否移动到垃圾桶中
		float ScreenX = (G.CGPanel.StartX + mX) * n_ImagePanel.ImagePanel.AScale / n_ImagePanel.ImagePanel.AScaleMid;
		float ScreenY = (G.CGPanel.StartY + mY) * n_ImagePanel.ImagePanel.AScale / n_ImagePanel.ImagePanel.AScaleMid;
		
		if( G.CGPanel.myRecycler.isInside( ScreenX, ScreenY ) ) {
			
			if( this.isMousePress ) {
				if( this is GVar || this is n_GNote.GNote ) {
					
					if( G.SimulateMode ) {
						n_Debug.Warning.WarningMessage = "仿真模式下无法删除模块, 请先结束仿真";
						return;
					}
					this.Remove();
				}
				if( this is n_MyFileObject.MyFileObject ) {
					
					if( G.SimulateMode ) {
						n_Debug.Warning.WarningMessage = "仿真模式下无法删除模块, 请先结束仿真";
						return;
					}
					this.Remove();
					G.CGPanel.RefreshResourceError();
				}
			}
		}
	}
	
	//鼠标移动事件,当组件被拖动时返回 true
	public abstract int MouseMove1( int mX, int mY );
	
	//专用于面板鼠标移动事件
	public bool MouseMove2( int mX, int mY )
	{
		if( !isHighLight ) {
			return false;
		}
		//菜单鼠标移动事件
		if( this.VPanel == null ) {
			return false;
		}
		return this.VPanel.MouseMove( mX, mY );
	}
	
	//-----------------------------------------------------
	
	//显示调试数据
	public void DrawDebug_old( Graphics g, int SX, int SY )
	{
		if( (G.DebugMode || G.SimulateMode) && DebugOpen ) {
			int xoff = 0; //(Width - 200) / 2;
			g.FillRectangle( DebugBackBrush, SX + xoff, SY + Height + 10, 200, 100 );
			g.DrawRectangle( Pens.DimGray, SX + xoff, SY + Height + 10, 200, 100 );
			g.DrawString( GetDebugData( 0 ).ToString(), n_GUIset.GUIset.DebugFont, DebugTextBrush, SX + xoff, SY + Height + 32 );
			
			int tempMinDebugData = GetDebugData( 0 );
			int tempMaxDebugData = MinDebugData;
			
			float STY = SY + Height + 10;
			float ENY = STY + 100;
			float STX = SX + xoff;
			float ENX = STX + 200;
			
			try{
			g.DrawString( MaxDebugData.ToString(), GUIset.ModuleNameFont, Brushes.DimGray, STX - 35, STY - 15 );
			g.DrawString( MinDebugData.ToString(), GUIset.ModuleNameFont, Brushes.DimGray, STX - 35, ENY );
			g.DrawString( GetDebugData( 0 ).ToString(), GUIset.ModuleNameFont, Brushes.OrangeRed, STX - 40, ENY - (GetDebugData( 0 )-MinDebugData)*100/(MaxDebugData-MinDebugData) - 8 );
			
			for( int i = 0; i < 200; ++i ) {
				//g.DrawLine( Pens.WhiteSmoke, STX + i, ENY - GetDebugData( i )/5, STX + i, ENY );
				g.DrawLine( Pens.Red, STX + i, ENY - (GetDebugData( i )-MinDebugData)*100/(MaxDebugData-MinDebugData), STX + i + 1, ENY - (GetDebugData( i+1 )-MinDebugData)*100/(MaxDebugData-MinDebugData) );
				
				if( tempMinDebugData > GetDebugData( i ) ) {
					tempMinDebugData = GetDebugData( i );
				}
				if( tempMaxDebugData < GetDebugData( i ) ) {
					tempMaxDebugData = GetDebugData( i );
				}
			}
			}catch {
				
			}
			int Ar = (tempMaxDebugData - tempMinDebugData) / 10;
			if( Ar < 30 ) {
				Ar = 30;
			}
			
			tempMinDebugData -= Ar;
			tempMaxDebugData += Ar;
			
			//这里自动放缩
			//MinDebugData = tempMinDebugData;
			//MaxDebugData = tempMaxDebugData;
			
			//这里不自动放缩
			if( MinDebugData > tempMinDebugData ) MinDebugData = tempMinDebugData;
			if( MaxDebugData < tempMaxDebugData ) MaxDebugData = tempMaxDebugData;
		}
	}
	
	//显示调试数据
	public void DrawDebug( Graphics g, int SX, int SY )
	{
		if( (G.DebugMode || G.SimulateMode) && DebugOpen ) {
			
			Color c = Color.Black;
			if( this is GVar ) {
				c = Color.CornflowerBlue;
			}
			if( this is n_HardModule.HardModule ) {
				c = Color.Orange;
			}
			LinePen1.Color = c;
			DebugTextBrush.Color = Color.FromArgb( 40, c );
			
			int xoff = 0; //(Width - 200) / 2;
			//g.FillRectangle( GUI, SX + xoff, SY + Height + 10, 200, 100 );
			
			//g.DrawRectangle( Pens.Silver, SX + xoff, SY + Height + 10, 200, 100 );
			g.DrawLine( Pens.Silver, SX + xoff, SY + Height + 10, SX + xoff, SY + Height + 10 + 100 );
			
			//绘制大数字
			g.DrawString( GetDebugData( 0 ).ToString(), n_GUIset.GUIset.DebugFont, DebugTextBrush, SX + xoff, SY + Height + 32 );
			
			int tempMinDebugData = GetDebugData( 0 );
			int tempMaxDebugData = MinDebugData;
			
			float STY = SY + Height + 10;
			float ENY = STY + 100;
			float STX = SX + xoff;
			float ENX = STX + 200;
			
			try{
			g.DrawString( MaxDebugData.ToString(), GUIset.ModuleNameFont, Brushes.Gray, STX - 35, STY - 15 );
			g.DrawString( MinDebugData.ToString(), GUIset.ModuleNameFont, Brushes.Gray, STX - 35, ENY );
			g.DrawString( GetDebugData( 0 ).ToString(), GUIset.ModuleNameFont, Brushes.Black, STX - 40, ENY - (GetDebugData( 0 )-MinDebugData)*100/(MaxDebugData-MinDebugData) - 8 );
			
			for( int i = 0; i < 200; ++i ) {
				//g.DrawLine( Pens.WhiteSmoke, STX + i, ENY - GetDebugData( i )/5, STX + i, ENY );
				float y1 = ENY - (GetDebugData( i )-MinDebugData)*100/(MaxDebugData-MinDebugData);
				float y2 = ENY - (GetDebugData( i+1 )-MinDebugData)*100/(MaxDebugData-MinDebugData);
				//g.DrawLine( LinePen0, STX + i, y1, STX + i + 1, y2 );
				
				int ap = (200 - i) * 2;
				if( ap > 255 ) {
					ap = 255;
				}
				LinePen1.Color = Color.FromArgb( ap, c );
				g.DrawLine( LinePen1, STX + i, y1, STX + i + 1, y2 );
				
				if( tempMinDebugData > GetDebugData( i ) ) {
					tempMinDebugData = GetDebugData( i );
				}
				if( tempMaxDebugData < GetDebugData( i ) ) {
					tempMaxDebugData = GetDebugData( i );
				}
			}
			}catch {
				
			}
			int Ar = (tempMaxDebugData - tempMinDebugData) / 10;
			if( Ar < 30 ) {
				Ar = 30;
			}
			
			tempMinDebugData -= Ar;
			tempMaxDebugData += Ar;
			
			//这里自动放缩
			//MinDebugData = tempMinDebugData;
			//MaxDebugData = tempMaxDebugData;
			
			//这里不自动放缩
			if( MinDebugData > tempMinDebugData ) MinDebugData = tempMinDebugData;
			if( MaxDebugData < tempMaxDebugData ) MaxDebugData = tempMaxDebugData;
		}
	}
	
	//添加一个数据
	public void AddDebugData( int d )
	{
		DebugIndex++;
		if( DebugIndex == DebugLength ) {
			DebugIndex = 0;
		}
		DebugValue[DebugIndex] = d;
	}
	
	//获取指定的数据
	public int GetDebugData( int i )
	{
		i = DebugIndex - i;
		if( i < 0 ) {
			i += DebugLength;
		}
		return DebugValue[i];
	}
}
}



